home *** CD-ROM | disk | FTP | other *** search
/ Mac-Source 1994 July / Mac-Source_July_1994.iso / C and C++ / Entertainment / MacMud / Sockets / socket.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-03-22  |  36.8 KB  |  1,506 lines  |  [TEXT/MPS ]

  1. /*
  2.  *    A more or less BSD compatable socket library for MacTCP
  3.  *    
  4.  *    Summer 1989, Tom Milligan, University of Toronto Computing Services
  5.  *
  6.  *
  7.  *    The following calls are implemented
  8.  *
  9.  *        socket
  10.  *        bind
  11.  *        listen
  12.  *        accept
  13.  *        connect
  14.  *        read
  15.  *        recv
  16.  *        recvfrom
  17.  *        write
  18.  *        writev
  19.  *        send
  20.  *        sendto
  21.  *        select
  22.  *        close
  23.  *        getdtablesize
  24.  *        getsockname
  25.  *        getpeername
  26.  *        shutdown
  27.  *        fcntl(F_DUPFD)
  28.  *        fcntl(F_GETFL)
  29.  *        fcntl(F_SETFL,FNDELAY)
  30.  *        dup
  31.  *        dup2
  32.  *        ioctl(FIONBIO)
  33.  *        ioctl(FIONREAD)
  34.  *
  35.  *    Non-blocking I/O is supported. All calls which would block return
  36.  *    immediately with an 'error' indicating so. Select() may be used to
  37.  *    determine when an operation can be performed.
  38.  *
  39.  *    Ioctl(FIONBIO) or fcntl(F_SETFL,FNDELAY)  can be used to toggle the
  40.  *    blocking status of a socket.
  41.  *
  42.  *    In a blocking situation, accept() and read() return EWOULDBLOCK and 
  43.  *    refuse to do anything. Select() for read() to learn when a incoming 
  44.  *    connection is available. 
  45.  *
  46.  *    Connect() and write() (which shouldn't take too long anyway) start 
  47.  *    the operation and return EINPROGRESS. Select for write() to learn
  48.  *    when connect() has completed. Write() on a socket which is still
  49.  *    'inprogress' return EALREADY.
  50.  *
  51.  *
  52.  *    Socket operations are single threaded and half-duplex. Fixing this is
  53.  *    left as an execise for the reader. Shouldn't be a terrible problem
  54.  *    anyway. Read() never blocks and write() only blocks for long if there
  55.  *    is a problem.
  56.  *
  57.  *    Calls which find the socket busy will return EALREADY. These are
  58.  *    read() or write() with a connect() or write() in progress.
  59.  *
  60.  *
  61.  *    Socket options are not supported. Hence no setsockopt() and getsockopt() 
  62.  *    calls.
  63.  *
  64.  *
  65.  *    The flags to the send() and recv() calls are not supported. In particular,
  66.  *    this means that out of band data is not supported.
  67.  *
  68.  *
  69.  *    Readv() and writev() are not implemented.
  70.  *
  71.  *
  72.  *    All calls which encounter an error will set the global variable errno
  73.  *    to indicate the problem. Some common values for errno are...
  74.  *
  75.  *        EBADF        the socket parameter is not a valid socket descriptor.
  76.  *        
  77.  *        EFAULT       a pointer parameters is rubbish.
  78.  *        
  79.  *        EINVAL       a non-pointer parameters is rubbish.
  80.  *
  81.  *        ENOTCONN     the socket should be in a connected state for this 
  82.  *                   operation, but isn't.
  83.  *
  84.  *        EISCONN      the socket is already connected.
  85.  *
  86.  * ----------------- non-blocking I/O
  87.  *
  88.  *        EWOULDBLOCK  accept() or one of the read() calls would block. 
  89.  *
  90.  *        EINPROGRESS  connect() or one of the write() operations has been 
  91.  *                   started.
  92.  *
  93.  * ----------------- SINGLE THREAD
  94.  *
  95.  *        EALREADY     an operation is already in progress on the socket.
  96.  *
  97.  * ----------------
  98.  *
  99.  *        EBUG           an internal error occured.
  100.  */
  101.  
  102.      
  103. #include <Events.h>
  104. #include <types.h>
  105. #include <stdio.h>
  106.  
  107. /* unixincludes */
  108. #include <sys/types.h>
  109. #include <sys/time.h>
  110. #include <sys/errno.h>
  111. #include <sys/socket.h>
  112. #include <netinet/in.h>
  113. #include <sys/file.h>
  114. #include <sys/ioctl.h>
  115.  
  116. #include "tcpglue.h"
  117. #define    SOCKET
  118. #include "socket.internal.h"
  119.  
  120.  
  121. /*
  122.  *    s_socket(domain, type, protocol)
  123.  *
  124.  *        socket creates a MacTCP socket and returns a descriptor.
  125.  *                 
  126.  *        Domain must be AF_INET
  127.  *         
  128.  *        Type may be SOCK_STREAM to create a TCP socket or 
  129.  *        SOCK_DGRAM to create a UDP socket.
  130.  *                 
  131.  *        Protocol is ignored.
  132.  *                 
  133.  *        TCP sockets provide sequenced, reliable, two-way connection
  134.  *        based byte streams. (Albeit, half-duplex one-operation-at-a-time.)
  135.  *
  136.  *        A TCP socket must be in a connected
  137.  *        state before any data may be sent or received on it. A 
  138.  *        connection to another socket is created with a connect() call
  139.  *        or the listen() and accept() calls.
  140.  *        Once connected, data may be transferred using read() and
  141.  *        write() calls or some variant of the send() and recv()
  142.  *        calls. When a session has been completed a close() may  be
  143.  *        performed.
  144.  *
  145.  *        Out-of-band data transmission is not supported. 
  146.  *        
  147.  *        A UDP socket supports the exchange of datagrams (connectionless, 
  148.  *        unreliable messages of a fixed maximum length) with  
  149.  *        correspondents named in send() calls. Datagrams are
  150.  *        generally received with recv(), which returns the next
  151.  *        datagram with its return address.
  152.  *
  153.  *        An fcntl() or ioctl() call can be used to enable non-blocking I/O.
  154.  *
  155.  *        The return value is a descriptor referencing the socket or -1
  156.  *        if an error occurs, in which case global variable errno is
  157.  *        set to one of:
  158.  *
  159.  *            ENOMEM                Failed to allocate memory for the socket
  160.  *                              data structures.
  161.  *        
  162.  *            EAFNOSUPPORT         Domain wasn't AF_INET.
  163.  *
  164.  *            ESOCKTNOSUPPORT     Type wasn't SOCK_STREAM or SOCK_DGRAM.
  165.  *
  166.  *            EMFILE              The socket descriptor table is full.
  167.  */
  168. s_socket(domain, type, protocol)
  169.     int domain;
  170.     int type;
  171.     int protocol;
  172. {
  173.     SocketPtr sp;
  174.     int s;
  175.  
  176. #if    SOCK_DEBUG >= 3
  177.     dprintf("s_socket:\n");
  178. #endif
  179.  
  180.     /*
  181.      * Support only Internet family
  182.      */
  183.     if (domain != AF_INET)
  184.         return(sock_err(EAFNOSUPPORT));
  185.         
  186.     switch(type) 
  187.     {
  188.         case SOCK_DGRAM:
  189.             protocol = IPPROTO_UDP;
  190.             break;
  191.         case SOCK_STREAM:
  192.             protocol = IPPROTO_TCP;
  193.             break;
  194.         default:
  195.             return(sock_err(ESOCKTNOSUPPORT));
  196.     }
  197.         
  198.     /*
  199.      *    Create a socket table entry 
  200.      */
  201.     s = sock_free_fd(0);        /* Get next free file descriptor */
  202.     if (s == -1)
  203.         return(sock_err(EMFILE));
  204.     sp = &sockets[s];
  205.     sp->fd = s;
  206.     sp->protocol = protocol;
  207.     bzero(&sp->sa, sizeof(struct sockaddr_in));
  208.     sp->sa.sin_family        = AF_INET;
  209.     sp->status                = SOCK_STATUS_USED;
  210.     sp->nonblocking            = false;
  211.  
  212.  
  213.     /* Create a new stream on the socket. */
  214.     switch(sp->protocol) 
  215.     {
  216.         case IPPROTO_UDP:
  217.             /* udp streams are not created until the last minute */
  218.             /* because we dont know if the caller wants to assign */
  219.             /* a special port number yet (via bind) and mactcp */
  220.             /* assigns udp port numbers at stream creation */
  221.             sp->sstate = SOCK_STATE_NO_STREAM;
  222.             break;
  223.  
  224.         case IPPROTO_TCP:
  225.             /* the tcp stream is created now because tcp port numbers */
  226.             /* are assigned during active/passiveOpen which is done */
  227.             /* during listen or connect */
  228.             sp->sstate = SOCK_STATE_UNCONNECTED;
  229.             if (sock_tcp_new_stream(sp) < 0)
  230.                 return(-1); /* sock_err already called */
  231.     }
  232.  
  233.     return(s);
  234. }
  235.  
  236.  
  237. /*
  238.  *    s_bind(s, name, namelen)
  239.  *
  240.  *        bind requests that the name (ip address and port) pointed to by 
  241.  *        name be assigned to the socket s.
  242.  *        
  243.  *        The return value is 0 on success or -1 if an error occurs,
  244.  *        in which case global variable errno is set to one of:
  245.  *
  246.  *        EAFNOSUPPORT        The address family in name is not AF_INET.
  247.  *        
  248.  *        EINVAL              The socket is already bound to an address.
  249.  *        
  250.  *        EADDRNOTAVAIL       The specified address is  not  available
  251.  *                             from the local machine. ie. the address
  252.  *                            portion of name was not this machine's address.
  253.  *
  254.  *        MacTCP does not separate name binding and connection establishment.
  255.  *        Therefore the port number is not verified, just stored for later use.
  256.  *
  257.  *        If a specific local port is not required, bind is optional in this
  258.  *        implementation.
  259.  */    
  260. s_bind(s, name, namelen) 
  261.     int s; 
  262.     struct sockaddr_in *name; 
  263.     int namelen;
  264. {
  265.     SocketPtr sp;
  266.     
  267. #if    SOCK_DEBUG >= 3
  268.     dprintf("s_bind: bind %d to %08x/%d\n",
  269.         s, name->sin_addr.s_addr, name->sin_port);
  270. #endif
  271.  
  272.     if (! sock_good_fd(s))
  273.         return(sock_err(EBADF));
  274.     sp = &sockets[s];
  275.         
  276.     if (namelen < sizeof(struct sockaddr_in))
  277.         return(sock_err(EINVAL));
  278.  
  279.     if (!goodptr(name)) 
  280.         return(sock_err(EFAULT));
  281.  
  282.     if (name->sin_family != AF_INET)
  283.         return(sock_err(EAFNOSUPPORT));
  284.  
  285.     if (sp->sa.sin_port != 0) /* already bound */
  286.         return(sock_err(EINVAL));
  287.  
  288.     /*
  289.      *    If client passed a local IP address, assure it is the right one
  290.      */
  291.     if (name->sin_addr.s_addr != 0) 
  292.     {
  293.         if (name->sin_addr.s_addr != xIPAddr())
  294.             return(sock_err(EADDRNOTAVAIL));
  295.     }
  296.  
  297.     /*
  298.      *    NOTE: can't check a TCP port for EADDRINUSE
  299.      *    just save the address and port away for connect or listen or...
  300.      */
  301.     sp->sa.sin_addr.s_addr = name->sin_addr.s_addr;
  302.     sp->sa.sin_port = name->sin_port;
  303.     return(0);
  304. }
  305.  
  306. /*
  307.  *    s_connect - initiate a connection on a MacTCP socket
  308.  *
  309.  *        If the parameter s is a UDP socket,
  310.  *        then  this  call specifies the address to  which  datagrams
  311.  *        are  to  be  sent, and the only address from which datagrams
  312.  *        are to be received.  
  313.  *             
  314.  *        If it is a TCP socket, then this call attempts to make a 
  315.  *        connection to another socket. The other socket is specified 
  316.  *        by an internet address and port.
  317.  *             
  318.  *        TCP sockets may successfully connect() only once;
  319.  *             
  320.  *        UDP sockets may use connect() multiple times to change
  321.  *        their association. UDP sockets may dissolve the association
  322.  *        by connecting to an invalid address, such as a null
  323.  *        address.
  324.  *        
  325.  *        If the connection or binding succeeds, then 0 is returned.
  326.  *        Otherwise a -1 is returned, and a more specific error code
  327.  *        is stored in errno.
  328.  *        
  329.  *        EAFNOSUPPORT        The address family in addr is not AF_INET.
  330.  *        
  331.  *        EHOSTUNREACH        The TCP connection came up half-way and 
  332.  *                          then failed.
  333.  *             
  334.  *    -------------- some day instead of EHOSTUNREACH -----------------
  335.  *        
  336.  *        EADDRNOTAVAIL       The specified address is not available
  337.  *                            on the remote machine.
  338.  *        
  339.  *        ETIMEDOUT           Connection establishment timed out
  340.  *                            without establishing a connection.
  341.  *        
  342.  *        ECONNREFUSED        The attempt to  connect  was  forcefully
  343.  *                            rejected.
  344.  *        
  345.  *        ENETUNREACH         The network is not reachable from here.
  346.  *        
  347.  *        EHOSTUNREACH        The host is not reachable from here.
  348.  *        
  349.  *        EADDRINUSE          The address is already in use.
  350.  */
  351. s_connect(s, addr, addrlen)
  352.     int s;
  353.     struct sockaddr_in *addr;
  354.     int addrlen;
  355. {
  356.     SocketPtr sp;
  357.     
  358. #if SOCK_DEBUG >= 2
  359.     dprintf("s_connect: connect %d to %08x/%d\n",
  360.         s, addr->sin_addr.s_addr, addr->sin_port);
  361. #endif
  362.     if (! sock_good_fd(s))
  363.         return(sock_err(EBADF));
  364.         
  365.     if (addrlen != sizeof(struct sockaddr_in))
  366.         return(sock_err(EINVAL));
  367.  
  368.     if (! goodptr(addr))
  369.         return(sock_err(EFAULT));
  370.  
  371.     if (addr->sin_family != AF_INET)
  372.         return(sock_err(EAFNOSUPPORT));
  373.  
  374.     sp = &sockets[s];
  375.     switch(sp->protocol) 
  376.     {
  377.         case IPPROTO_UDP:
  378.             return(sock_udp_connect(sp,addr));
  379.  
  380.         case IPPROTO_TCP:
  381.             return(sock_tcp_connect(sp,addr));
  382.     }
  383. }
  384.  
  385. /*
  386.  *    s_listen()
  387.  *
  388.  *        To accept connections, a socket is first created  with
  389.  *        socket(), a backlog for incoming connections is specified
  390.  *        with listen() and then the  connections  are  accepted  with
  391.  *        accept(). The listen() call applies only to TCP sockets.
  392.  *        
  393.  *        The qlen parameter is supposed to define the maximum length
  394.  *        the queue of pending connections may grow to. It is ignored.
  395.  *        
  396.  *        A 0 return value indicates success; -1 indicates an error.
  397.  *        
  398.  *        EOPNOTSUPP          s is not a TCP socket.
  399.  */
  400. s_listen(s, qlen)
  401.     int s;
  402.     int qlen;
  403. {
  404. #pragma unused(qlen)
  405.     SocketPtr sp;
  406.     
  407. #if SOCK_DEBUG >= 2
  408.     dprintf("listen: listen %d\n", s);
  409. #endif
  410.     if (! sock_good_fd(s))
  411.         return(sock_err(EBADF));
  412.         
  413.     sp = &sockets[s];    
  414.     switch(sp->protocol) 
  415.     {
  416.         case IPPROTO_UDP:
  417.             return(sock_err(EOPNOTSUPP));
  418.         
  419.         case IPPROTO_TCP:
  420.             return(sock_tcp_listen(sp));
  421.     }
  422. }
  423.  
  424. /*
  425.  *    s_accept(s, addr, addrlen)
  426.  *
  427.  *        s is a socket that has been created with socket,  bind, listen.
  428.  *        
  429.  *        Accept  extracts the  first  connection  on the queue of pending 
  430.  *        connections, creates a new socket with the same properties of s 
  431.  *        and allocates  a  new  file  descriptor,  ns, for the socket.
  432.  *        
  433.  *        If no pending connections are present on the queue, and the socket
  434.  *        is not marked as non-blocking, accept blocks the caller until
  435.  *        a connection is present. 
  436.  *        
  437.  *        If the socket is marked non-blocking  and  no pending connections 
  438.  *        are present on the queue, accept returns an error EWOULDBLOCK.
  439.  *        
  440.  *        The accepted socket, ns, is used to read and write data to and
  441.  *        from the socket which connected to this one; it is not  used
  442.  *        to  accept  more connections.  The original socket s remains
  443.  *        open for accepting further connections.
  444.  *        
  445.  *        The argument addr is a result parameter that  is  filled  in
  446.  *        with  the  address of the connecting socket. The addrlen is 
  447.  *        a value-result  parameter; it should initially contain the
  448.  *        amount of space pointed to by addr; on return it will contain 
  449.  *        the actual length (in bytes) of the address returned.
  450.  *        
  451.  *        This call is used with TCP sockets only.
  452.  *        
  453.  *        It is possible to select a socket  for  the  purposes  of
  454.  *        doing an accept by selecting it for read.
  455.  *        
  456.  *        The call returns -1 on error.  If it succeeds, it returns  a
  457.  *        non-negative  integer  that is a descriptor for the accepted
  458.  *        socket.
  459.  *        
  460.  *        EOPNOTSUPP          s is not a TCP socket.
  461.  *        
  462.  *        EMFILE              The socket descriptor table is full.
  463.  */
  464. s_accept(s, addr, addrlen)
  465.     int s;
  466.     struct sockaddr_in *addr;
  467.     int *addrlen;
  468. {
  469.     SocketPtr sp;
  470.  
  471. #if SOCK_DEBUG >= 2
  472.     dprintf("s_accept: %d\n", s);
  473. #endif
  474.     if (! sock_good_fd(s))
  475.         return(sock_err(EBADF));
  476.         
  477.     if (!goodptr(addr) || !goodptr(addrlen)) 
  478.         return(sock_err(EFAULT));
  479.  
  480.     if (*addrlen < 0) 
  481.         return(sock_err(EINVAL));
  482.  
  483.     if (sock_free_fd(0) == -1)
  484.         return(sock_err(EMFILE));
  485.  
  486.     sp = &sockets[s];
  487.     switch(sp->protocol) 
  488.     {
  489.         case IPPROTO_UDP:
  490.             return(sock_err(EOPNOTSUPP));
  491.         case IPPROTO_TCP:
  492.             return(sock_tcp_accept(sp,addr,addrlen));
  493.     }
  494. }
  495.  
  496.  
  497. /*
  498.  *    s_close(s)
  499.  *
  500.  *        The close call destroys the socket s. If this is the last reference 
  501.  *        to the underlying MacTCP stream, then the stream will be released.
  502.  *    
  503.  *        A 0 return value indicates success; -1 indicates an error.
  504.  *
  505.  *        NOTE: if non-blocking I/O is enabled EWOULDBLOCK will be returned
  506.  *            if there are TCP writes in progress. (UDP writes are
  507.  *            performed synchronously.)
  508.  *
  509.  *              All reads are terminated and unread data is lost.
  510.  */
  511. s_close(s) 
  512.     int s;
  513. {
  514.     int t;
  515.     SocketPtr sp;
  516.     int status;
  517.     
  518. #if SOCK_DEBUG >= 2
  519.     dprintf("s_close: %d\n", s);
  520. #endif
  521.     if (! sock_good_fd(s))
  522.         return(sock_err(EBADF));
  523.         
  524.     sp = &sockets[s];
  525.  
  526.     /*
  527.      *    Look for duplicates of the socket.  Only close down the connection
  528.      *    if there are no duplicates(i.e. socket not dup'd).
  529.      */
  530.      for (t = 0; t < NUM_SOCKETS; t++) 
  531.      {
  532.          if (t == s)
  533.             continue;
  534.          if (!(sockets[t].status & SOCK_STATUS_USED))
  535.             continue;
  536.         if (sockets[t].protocol == sp->protocol &&
  537.             ((sockets[t].protocol == IPPROTO_UDP && 
  538.               sockets[t].pb.udp.udpStream == sp->pb.udp.udpStream)  ||
  539.              (sockets[t].protocol == IPPROTO_TCP && 
  540.               sockets[t].pb.tcp.tcpStream == sp->pb.tcp.tcpStream)))
  541.         {    /* found a duplicate */
  542. #if SOCK_DEBUG >= 3
  543.             dprintf("s_close: found a dup at %d(%d, don't close stream\n",
  544.                 t, sockets[t].protocol);
  545. #endif
  546.             sock_clear_fd(s);
  547.             return(0);
  548.         }
  549.     }
  550.  
  551.     /*
  552.      *    No duplicates, close the stream. 
  553.      */
  554.     switch(sp->protocol) 
  555.     {
  556.         case IPPROTO_UDP:
  557.             status = sock_udp_close(sp);
  558.             break;
  559.             
  560.         case IPPROTO_TCP:
  561.             status = sock_tcp_close(sp);
  562.             break;
  563.     }
  564.     if (status != EWOULDBLOCK) {
  565.         sock_clear_fd(s);
  566.     }
  567.     return(status);
  568. }
  569.  
  570.  
  571. /*
  572.  *    s_read(s, buffer, buflen)
  573.  *
  574.  *    s_recv(s, buffer, buflen, flags)
  575.  *    
  576.  *    s_recvfrom(s, buffer, buflen, flags, from, fromlen)
  577.  *    
  578.  *        read() attempts to read nbytes of data from the socket s.  
  579.  *        
  580.  *        recv() and recvfrom() attempt to receive a message (ie a datagram) 
  581.  *        on the socket s. 
  582.  *
  583.  *        from returns the address of the socket which sent the message.
  584.  *        fromlen is the usual value-result length parameter. 
  585.  *        
  586.  *        Typically, read() is used with a TCP stream and recv() with
  587.  *        UDP where the idea of a message makes more sense. But in fact,
  588.  *        read() and recv() are equivalent.
  589.  *        
  590.  *        For UDP...
  591.  *            If a message (ie. datagram) is too long to fit in the supplied 
  592.  *            buffer, excess bytes will be discarded..
  593.  *
  594.  *            If no messages are available at the socket, the receive call
  595.  *            waits for a message to arrive, unless the socket is non-
  596.  *            blocking in which case -1 is returned with errno set to 
  597.  *            EWOULDBLOCK.
  598.  *
  599.  *        For TCP...
  600.  *            Regardless of non-blocking status, if less data is available
  601.  *            than has been requested, only that much data is returned.
  602.  *
  603.  *            If the socket is marked for non-blocking I/O, and the socket 
  604.  *            is empty, the operation will fail with the error EWOULDBLOCK.
  605.  *            Otherwise, the operation will block until data is available 
  606.  *            or an error occurs.
  607.  *
  608.  *            A return value of zero indicates that the stream has been
  609.  *            closed and all data has already been read. ie. end-of-file.
  610.  *        
  611.  *        Flags is ignored.
  612.  *        
  613.  *        If successful, the number of bytes actually received is
  614.  *        returned. Otherwise, a -1 is returned and the global variable
  615.  *        errno is set to indicate the error. 
  616.  *        
  617.  *        ESHUTDOWN    The socket has been shutdown for receive operations.
  618.  */
  619. s_read(s, buffer, buflen)
  620.     int s;
  621.     char *buffer;
  622.     int buflen;
  623. {
  624.     int fromlen = 0;
  625.     return(s_recvfrom(s, buffer, buflen, 0, NULL, &fromlen));
  626. }
  627.  
  628. s_recv(s, buffer, buflen, flags)
  629.     int s;
  630.     char *buffer;
  631.     int buflen;
  632.     int flags;
  633. {
  634.     int fromlen = 0;
  635.     return(s_recvfrom(s, buffer, buflen, flags, NULL, &fromlen));
  636. }
  637.  
  638. s_recvfrom (s, buffer, buflen, flags, from, fromlen)
  639.     int s;
  640.     char *buffer;
  641.     int buflen;
  642.     int flags;
  643.     struct sockaddr_in *from;
  644.     int *fromlen;
  645. {
  646.     SocketPtr sp;
  647.  
  648. #if SOCK_DEBUG >= 3
  649.     dprintf ("s_recvfrom: %d\n", s);
  650. #endif
  651.     if (s < 0 || s >= NUM_SOCKETS)
  652.         return (sock_err (EBADF));
  653.         
  654.     sp = &sockets[s];
  655.     if (! is_used (sp))
  656.         return (sock_err (EBADF));
  657.         
  658.     if (!goodptr(buffer))
  659.         return (sock_err (EFAULT));
  660.         
  661.     if (buflen <= 0 || buflen > 65535)
  662.         return(sock_err(EINVAL));
  663.         
  664.     if (from != NULL && !goodptr(from))
  665.         return(sock_err(EFAULT));
  666.         
  667.     if (!goodptr(fromlen))
  668.         return(sock_err(EFAULT));
  669.         
  670.     if (*fromlen <0)
  671.         return(sock_err(EINVAL));
  672.  
  673.     if (sock_noread(sp))
  674.         return(sock_err(ESHUTDOWN));
  675.  
  676.     switch(sp->protocol) 
  677.     {
  678.         case IPPROTO_UDP:
  679.             return(sock_udp_recv(sp, buffer, buflen, flags, from, fromlen));
  680.  
  681.         case IPPROTO_TCP:
  682.             return(sock_tcp_recv(sp, buffer, buflen, flags));
  683.     }
  684. }
  685.  
  686.  
  687. /*
  688.  *    s_write(s, buffer, buflen)
  689.  *
  690.  *    s_writev(s, iov, iovcnt)
  691.  *
  692.  *    s_send(s, buffer, buflen, flags)
  693.  *
  694.  *    s_sendto(s, buffer, buflen, flags, to, tolen)
  695.  *
  696.  *        write() attempts to write nbytes of data to the socket s from
  697.  *        the buffer pointed to by buffer.
  698.  *        
  699.  *        writev() gathers the output data from the buffers specified 
  700.  *        by the members of the iov array. Each iovec entry specifies 
  701.  *        the base address and length of an area in memory from which 
  702.  *        data should be written.
  703.  *        
  704.  *        send() and sendto() are used to transmit a message to another 
  705.  *        socket on the socket s.
  706.  *
  707.  *        Typically, write() is used with a TCP stream and send() with
  708.  *        UDP where the idea of a message makes more sense. But in fact,
  709.  *        write() and send() are equivalent.
  710.  *        
  711.  *        For UDP...
  712.  *
  713.  *          Write() and send() operations are completed as soon as the
  714.  *          data is placed on the transmission queue.???????
  715.  *
  716.  *            The address of the target is given by to.
  717.  *
  718.  *            The message must be short enough to fit into one datagram.
  719.  *        
  720.  *            Buffer space must be available to hold the message to be 
  721.  *            transmitted, regardless of its non-blocking I/O state.
  722.  *        
  723.  *        For TCP...
  724.  *            Write() and send() operations are not considered complete
  725.  *            until all data has been sent and acknowledged.
  726.  *
  727.  *            If a socket is marked for non-blocking I/O, the operation
  728.  *            will return an 'error' of EINPROGRESS.
  729.  *        
  730.  *            If the socket is not marked for non-blocking I/O, the write will
  731.  *            block until space becomes available.
  732.  *        
  733.  *        write() and send() may be used only when the socket is in a connected
  734.  *        state, sendto() may be used at any time.
  735.  *
  736.  *        Flags is ignored.
  737.  *        
  738.  *        These calls return the number of bytes sent, or -1 if an error 
  739.  *        occurred.
  740.  *        
  741.  *        EINVAL           The sum of the iov_len values in the iov array was
  742.  *                         greater than 65535 (TCP) or 65507 (UDP) or there
  743.  *                       were too many entries in the array (16 for TCP or
  744.  *                       6 for UDP).
  745.  *
  746.  *        ESHUTDOWN        The socket has been shutdown for send operations.
  747.  *        
  748.  *        EMSGSIZE         The message is too big to send in one datagram. (UDP)
  749.  *
  750.  *        ENOBUFS          The transmit queue is full. (UDP)
  751.  */
  752.  
  753. s_write(s, buffer, buflen)
  754.     int s;
  755.     char *buffer;
  756.     int buflen;
  757. {
  758.     return(s_really_send(s, buffer, buflen, false, 0, NULL));
  759.  
  760. s_writev(s, iov, count)
  761.     int s;
  762.     struct iovec *iov;
  763.     int count;
  764. {
  765.     return(s_really_send(s, (char *)iov, count, true, 0, NULL));
  766.  
  767. s_send(s, buffer, buflen, flags)
  768.     int s;
  769.     char *buffer;
  770.     int buflen;
  771.     int flags;
  772. {
  773.     return(s_really_send(s, buffer, buflen, false, flags, NULL));
  774.  
  775. s_sendto (s, buffer, buflen, flags, to, tolen)
  776.     int s;
  777.     char *buffer;
  778.     int buflen;
  779.     int flags;
  780.     struct sockaddr_in *to;
  781.     int tolen;
  782. {
  783.     if (to != NULL && !goodptr(to))
  784.         return(sock_err(EFAULT));
  785.         
  786.     if (tolen < sizeof(struct sockaddr_in))
  787.         return(sock_err(EINVAL));
  788.  
  789.     return(s_really_send(s, buffer, buflen, false, flags, to));
  790. }
  791.  
  792. s_really_send(s, buffer, count, vector, flags, to)
  793.     int s;
  794.     char *buffer;
  795.     int count;
  796.     Boolean vector;
  797.     int flags;
  798.     struct sockaddr_in *to;
  799. {
  800.     SocketPtr sp;
  801.  
  802. #if SOCK_DEBUG >= 2
  803.     if (vector)
  804.         dprintf("s_really_send: %d  %d items", s, count);
  805.     else
  806.         dprintf("s_really_send: %d  %d bytes", s, count);
  807.     if (to != NULL)
  808.         dprintf(" to %08x/%d",to->sin_addr.s_addr,to->sin_port);
  809.     dprintf("\n");
  810. #endif
  811.     if (! sock_good_fd(s))
  812.         return(sock_err(EBADF));
  813.     sp = &sockets[s];
  814.  
  815. #if SOCK_DEBUG >= 2
  816.     dprintf("state %d\n",sp->sstate);
  817.     dprintf("peer %08x/%d\n",sp->peer.sin_addr.s_addr,sp->peer.sin_port);
  818. #endif
  819.     
  820.     if (sock_nowrite(sp))
  821.         return(sock_err(ESHUTDOWN));
  822.  
  823.     switch(sp->protocol) 
  824.     {
  825.         case IPPROTO_UDP:
  826.             if (to == NULL && sp->sstate != SOCK_STATE_CONNECTED) 
  827.                 return(sock_err(ENOTCONN));
  828.             return(sock_udp_send(sp, to, buffer, count, vector, flags));
  829.  
  830.         case IPPROTO_TCP:
  831.             if (to != NULL) /* sendto */
  832.                 return(sock_err(EOPNOTSUPP));
  833.             if (sp->sstate != SOCK_STATE_CONNECTED) 
  834.                 return(sock_err(ENOTCONN));
  835.             return(sock_tcp_send(sp, buffer, count, vector, flags));
  836.     }
  837. }
  838.  
  839.  
  840. /*
  841.  *    s_select(width, readfds, writefds, exceptfds, timeout)
  842.  *
  843.  *        select() examines the I/O descriptor  sets  whose  addresses
  844.  *        are  passed  in  readfds,  writefds, and exceptfds to see if
  845.  *        some of their descriptors are ready for reading,  ready  for
  846.  *        writing, or have an exceptional condition pending.  width is
  847.  *        the number of bits to be  checked  in  each  bit  mask  that
  848.  *        represent  a file descriptor; the descriptors from 0 through
  849.  *        width-1 in the  descriptor  sets  are  examined.   Typically
  850.  *        width  has  the  value  returned by getdtablesize for the
  851.  *        maximum number of file  descriptors.   On  return,  select
  852.  *        replaces  the  given descriptor sets with subsets consisting
  853.  *        of those descriptors that are ready for the requested opera-
  854.  *        tion.  The total number of ready descriptors in all the sets
  855.  *        is returned.
  856.  *
  857.  *        If timeout is not a NULL pointer,  it  specifies  a  maximum
  858.  *        interval  to wait for the selection to complete.  If timeout
  859.  *        is a NULL  pointer,  the  select  blocks  indefinitely.   To
  860.  *        effect  a  poll,  the  timeout argument should be a non-NULL
  861.  *        pointer, pointing to a zero-valued timeval structure.
  862.  *
  863.  *        Any of readfds, writefds, and exceptfds may be given as NULL
  864.  *        pointers if no descriptors are of interest.
  865.  *
  866.  *        Using select to open a socket for reading is analogous  to
  867.  *        performing an accept call.
  868.  *
  869.  *        select() returns the number of ready  descriptors  that  are
  870.  *        contained  in  the  descriptor  sets,  or  -1  if  an  error
  871.  *        occurred.  If the time limit expires then  select()  returns
  872.  *        0.   If select() returns with an error the descriptor sets 
  873.  *      will be unmodified.
  874.  */
  875. s_select(width, readfds, writefds, exceptfds, timeout)
  876.     int width;
  877.     unsigned long *readfds;
  878.     unsigned long *writefds;
  879.     unsigned long *exceptfds;
  880.     struct timeval *timeout;
  881. {
  882.     SocketPtr sp;
  883.     long count;
  884.     int s;
  885.     extern short __spin_abort;
  886.     long starttime, waittime;
  887.     unsigned long rd, wd, ed;
  888.     int errorHappened;
  889.  
  890. #if SOCK_DEBUG >= 2
  891.     dprintf("select:  socket: width %d\n",width);
  892. #endif
  893.     if (!goodptr(timeout) && timeout != NULL)
  894.         return(sock_err(EFAULT));
  895.     if (!goodptr(readfds) && readfds != NULL)
  896.         return(sock_err(EFAULT));
  897.     if (!goodptr(writefds) && writefds != NULL)
  898.         return(sock_err(EFAULT));
  899.     if (!goodptr(exceptfds) && exceptfds != NULL)
  900.         return(sock_err(EFAULT));
  901.         
  902. #if SOCK_DEBUG >= 3
  903.     dprintf("select: timeout %d sec, read %08x write %08x except %08x\n",
  904.         (timeout ? timeout->tv_sec : 99999), 
  905.         (readfds!=NULL ? *readfds : 0L),
  906.         (writefds!=NULL ? *writefds : 0L),
  907.         (exceptfds!=NULL ? *exceptfds : 0L));
  908. #endif
  909.  
  910.     if (width > 32)    /* for now..xxx. */
  911.         width = 32;
  912.     count = 0;
  913.     rd = 0; 
  914.     wd = 0; 
  915.     ed = 0;
  916.  
  917.     if (timeout) 
  918.     {
  919.         waittime = TVTOTICK(timeout->tv_sec,timeout->tv_usec);
  920.         starttime = TickCount();
  921.     }
  922. #if SOCK_DEBUG >= 5
  923.     dprintf("     starttime = %d(tics);  waittime = %d\n",starttime, waittime);
  924. #endif
  925.  
  926.     __spin_abort = 0;
  927.     do 
  928.     {
  929.         for (s = 0 , sp = sockets ; s < width && s < NUM_SOCKETS ; ++s, ++sp) 
  930.         {
  931.             if (is_used(sp)) 
  932.             {
  933.                 errorHappened = 0;
  934.                 
  935.                 /* Check if there is data or connection available. */
  936.                 if (readfds && sock_is_set(*readfds,s)) 
  937.                 {
  938.                     switch(sp->protocol) 
  939.                     {
  940.                         case IPPROTO_UDP:
  941.                             switch (sock_udp_can_recv(sp))
  942.                             {
  943.                                 case 1:
  944.                                     sock_set(rd,s);
  945.                                     ++count;
  946.                                     break;
  947.                                 case -1:
  948.                                     errorHappened = 1;
  949.                                     break;
  950.                             }
  951.                             break;
  952.                 
  953.                         case IPPROTO_TCP:
  954.                             if (sock_tcp_can_read(sp))
  955.                             {
  956.                                 sock_set(rd,s);
  957.                                 ++count;
  958.                             }
  959.                             break;
  960.                     }
  961.                 }
  962.                 if (writefds && sock_is_set(*writefds,s)) 
  963.                 {
  964.                     switch(sp->protocol) 
  965.                     {
  966.                         case IPPROTO_UDP:
  967.                             switch (sock_udp_can_send(sp))
  968.                             {
  969.                                 case 1:
  970.                                     sock_set(wd,s);
  971.                                     ++count;
  972.                                     break;
  973.                                 case -1:
  974.                                     errorHappened = 1;
  975.                                     break;
  976.                             }
  977.                             break;
  978.                 
  979.                         case IPPROTO_TCP:
  980.                             if (sock_tcp_can_write(sp))
  981.                             {
  982.                                 sock_set(wd,s);
  983.                                 ++count;
  984.                             }
  985.                             break;
  986.                     }
  987.                 }
  988.                 if (exceptfds && sock_is_set(*exceptfds,s)) 
  989.                 {
  990.                     if (errorHappened)  
  991.                     {
  992.                         sock_set(ed,s);
  993.                         ++count;
  994.                     }
  995.                 }
  996.             }
  997.         }
  998.         if (spinroutine != NULL) {
  999.             (*spinroutine)();
  1000.             if (__spin_abort)
  1001.                 break;
  1002.         }
  1003.     } 
  1004.     while(count == 0 &&(timeout == 0 || TickCount() - starttime < waittime));
  1005.  
  1006.     if (readfds)             
  1007.         *readfds = rd;
  1008.     if (writefds)             
  1009.         *writefds = wd;
  1010.     if (exceptfds)             
  1011.         *exceptfds = ed;
  1012. #if SOCK_DEBUG >= 5
  1013.     dprintf("     endtime = %d(tics)  count %d, read %08x write %08x except %08x\n",
  1014.         TickCount()-starttime,count,
  1015.         (readfds!=NULL ? *readfds : 0L),
  1016.         (writefds!=NULL ? *writefds : 0L),
  1017.         (exceptfds!=NULL ? *exceptfds : 0L));
  1018. #endif
  1019.     return(count);
  1020. }
  1021.     
  1022. /*
  1023.  *    s_getdtablesize()
  1024.  *
  1025.  *        The entries in the socket descriptor table are numbered with small
  1026.  *        integers starting at 0. getdtablesize returns the size of the 
  1027.  *        descriptor table.
  1028.  */
  1029. s_getdtablesize()
  1030. {
  1031.     return(NUM_SOCKETS);
  1032. }
  1033.  
  1034. /*
  1035.  *    s_getsockname(s, name, namelen)
  1036.  *
  1037.  *        getsockname returns the current name for the  socket s.
  1038.  *        Namelen should  be initialized to
  1039.  *        indicate the amount of space pointed to by name.  On  return
  1040.  *        it contains the actual size of the name returned (in bytes).
  1041.  *        
  1042.  *        A 0 is returned if the call succeeds, -1 if it fails.
  1043.  */
  1044.  
  1045. s_getsockname(s, name, namelen)
  1046.     int s;
  1047.     struct sockaddr_in *name;
  1048.     int *namelen;
  1049. {
  1050. #if SOCK_DEBUG >= 3
  1051.     dprintf("GETSOCKNAME: %d\n", s);
  1052. #endif
  1053.     if (! sock_good_fd(s))
  1054.         return(sock_err(EBADF));
  1055.  
  1056.     if (! goodptr(name))
  1057.         return(sock_err(EFAULT));
  1058.         
  1059.     if (*namelen < 0)
  1060.         return(sock_err(EINVAL));
  1061.  
  1062.     sock_copy_addr(&sockets[s].sa, name, *namelen);
  1063.     return(0);
  1064. }
  1065.  
  1066. /*
  1067.  *    s_getpeername(s, name, namelen)
  1068.  *
  1069.  *        getpeername returns the name of the peer connected to socket s.
  1070.  *
  1071.  *        The  int  pointed  to  by the namelen parameter
  1072.  *        should be  initialized  to  indicate  the  amount  of  space
  1073.  *        pointed  to  by name.  On return it contains the actual size
  1074.  *        of the name returned (in bytes).  The name is  truncated  if
  1075.  *        the buffer provided is too small.
  1076.  *        
  1077.  *        A 0 is returned if the call succeeds, -1 if it fails.
  1078.  */
  1079. s_getpeername(s, name, namelen)
  1080.     int s;
  1081.     struct sockaddr_in *name;
  1082.     int *namelen;
  1083. {
  1084.     SocketPtr sp;
  1085.  
  1086. #if SOCK_DEBUG >= 2
  1087.     dprintf("getpeername: socket %d\n", s);
  1088. #endif
  1089.     if (! sock_good_fd(s))
  1090.         return(sock_err(EBADF));        
  1091.  
  1092.     sp = &sockets[s];
  1093.     if (! is_used (sp))
  1094.         return (sock_err (EBADF));
  1095.  
  1096.     if (! goodptr(name))
  1097.         return(sock_err(EFAULT));
  1098.         
  1099.     if (*namelen < 0)
  1100.         return(sock_err(EINVAL));
  1101.  
  1102.     if (sp->sstate != SOCK_STATE_CONNECTED) 
  1103.         return(sock_err(ENOTCONN));
  1104.  
  1105.     sock_copy_addr(&sockets[s].peer, name, *namelen);
  1106.  
  1107.     return(0);
  1108. }
  1109.  
  1110. /*
  1111.  *    s_shutdown(s, how)
  1112.  *
  1113.  *        shutdown call causes all or part of a full-duplex
  1114.  *        connection on the socket s to be shut down.  If
  1115.  *        how is 0, then further receives will be disallowed.  If  how
  1116.  *        is  1,  then further sends will be disallowed.  If how is 2,
  1117.  *        then further sends and receives will be disallowed.
  1118.  *        
  1119.  *        A 0 is returned if the call succeeds, -1 if it fails.
  1120.  */
  1121. s_shutdown(s, how)
  1122.     int s;
  1123.     int how;
  1124. {
  1125.     SocketPtr sp;
  1126.     
  1127. #if SOCK_DEBUG >= 2
  1128.     dprintf("shutdown: shutdown %d\n", s);
  1129. #endif
  1130.     if (! sock_good_fd(s))
  1131.         return(sock_err(EBADF));
  1132.     sp = &sockets[s];
  1133.  
  1134.     switch(how) 
  1135.     {
  1136.         case 0 : 
  1137.             sp->status |= SOCK_STATUS_NOREAD;
  1138.             break;
  1139.             
  1140.         case 1 : 
  1141.             sp->status |= SOCK_STATUS_NOWRITE;
  1142.             break;
  1143.  
  1144.         case 2 :
  1145.             sp->status |= SOCK_STATUS_NOREAD | SOCK_STATUS_NOWRITE;
  1146.             break;
  1147.             
  1148.         default :
  1149.             return(sock_err(EINVAL));
  1150.     }
  1151.     return(0);
  1152. }
  1153.  
  1154. /*
  1155.  *    fcntl() operates on the socket s according to the order in cmd:
  1156.  *
  1157.  *        F_DUPFD    Like Dup. Returns a new descriptor which refers to the 
  1158.  *                same MacTCP stream as s and has the same descriptor 
  1159.  *                status.
  1160.  *
  1161.  *        F_GETFL    returns the descriptor status flags for s. The only
  1162.  *                flag supported is FNDELAY for non-blocking i/o.
  1163.  *
  1164.  *        F_SETFL    toggles descriptor status flags for s. The only
  1165.  *                 flag supported is FNDELAY for non-blocking i/o.
  1166.  *
  1167.  *        A dup or F_DUPFD operation copies the descriptor status flags
  1168.  *        maintained by F_SETFL, but once the copy is done, the two are
  1169.  *        disjoint. THIS IS DIFFERENT FROM UNIX.
  1170.  *
  1171.  *        Upon successful completion, the value  returned  depends  on
  1172.  *        cmd as follows:
  1173.  *            F_DUPFD   A new descriptor.
  1174.  *             F_GETFL   Value of flags.
  1175.  *            F_SETFL   0.
  1176.  *
  1177.  *        On error, a value of -1  is returned and errno is set to indicate 
  1178.  *        the error.
  1179.  *
  1180.  *        EBADF           s is not a valid open descriptor.
  1181.  *
  1182.  *        EMFILE          cmd is F_DUPFD and socket descriptor table is full.
  1183.  *
  1184.  *        EINVAL          cmd is F_DUPFD and arg  is  negative  or
  1185.  *                      greater   than   the  maximum  allowable
  1186.  *                      number (see getdtablesize).
  1187.  */
  1188. s_fcntl(s, cmd, arg)
  1189.     int s;
  1190.     unsigned int cmd;
  1191.     int arg;
  1192. {
  1193. #if SOCK_DEBUG >= 2
  1194.     dprintf("s_fcntl: %d\n", s);
  1195. #endif
  1196.  
  1197.     if (! sock_good_fd(s))
  1198.         return(sock_err(EBADF));
  1199.  
  1200.     switch(cmd) 
  1201.     {
  1202.         /*
  1203.          * Duplicate a socket.
  1204.          */
  1205.         case F_DUPFD : 
  1206.         {
  1207.             int s1;
  1208.             
  1209.             if (arg < 0 || arg >= NUM_SOCKETS)
  1210.                 return(sock_err(EINVAL));
  1211.             
  1212.             s1 = sock_free_fd(arg);
  1213.             if (s1 == -1)
  1214.                 return(sock_err(EMFILE));
  1215.             
  1216.             sock_dup_fd(s,s1);
  1217.             return(s1);
  1218.         }
  1219.         
  1220.         /*
  1221.          *  Get socket status.  This is like getsockopt().
  1222.          *  Only supported descriptor status is FNDELAY.
  1223.          */
  1224.         case F_GETFL : 
  1225.         {
  1226.             SocketPtr sp;
  1227.     
  1228.             sp = &sockets[s];
  1229.             if (sp->nonblocking)
  1230.                 return(FNDELAY);
  1231.             else
  1232.                 return(0);
  1233.         }
  1234.         
  1235.         /*
  1236.          *  Set socket status.  This is like setsockopt().
  1237.          *  Only supported descriptor status is FNDELAY.
  1238.          */
  1239.         case F_SETFL : 
  1240.         {
  1241.             SocketPtr sp;
  1242.     
  1243.             sp = &sockets[s];
  1244.             if (arg & FNDELAY)
  1245.                 sp->nonblocking = true;
  1246.             else
  1247.                 sp->nonblocking = false;
  1248.             
  1249.             return(0);
  1250.         }
  1251.     }
  1252. }
  1253.  
  1254. /*
  1255.  *    dup(s)
  1256.  *
  1257.  *    dup2(s, news)
  1258.  *
  1259.  *        dup() duplicates an existing socket descriptor.   The  argu-
  1260.  *        ment s is a small non-negative integer index in the per-
  1261.  *        process descriptor table.  The value must be less  than  the
  1262.  *        size  of  the  table, which is returned by getdtablesize(2).
  1263.  *        The new descriptor returned by the call is the  lowest  num-
  1264.  *        bered  descriptor  that  is not currently in use by the pro-
  1265.  *        cess.
  1266.  *
  1267.  *        In the second form  of  the  call,  the  value  of  the  new
  1268.  *        descriptor  desired  is  specified.   If  that descriptor is
  1269.  *        already in use, the descriptor is first deallocated as if  a
  1270.  *        close(2) call had been done first.
  1271.  *
  1272.  *        The value -1 is returned if an error occurs in either  call.
  1273.  *        The  external  variable  errno  indicates  the  cause of the
  1274.  *        error.
  1275.  *
  1276.  *        EBADF               s or  news is  not  a  valid  socket
  1277.  *                            descriptor.
  1278.  *
  1279.  *        EMFILE              Too many descriptors are active.
  1280.  */
  1281. s_dup(s)
  1282.     int s;
  1283. {
  1284.     return(s_fcntl(s, F_DUPFD, 0));
  1285. }
  1286.  
  1287. s_dup2(s, s1)
  1288.     int s;
  1289.     int s1;
  1290. {
  1291.     if (! sock_good_fd(s))
  1292.         return(sock_err(EBADF));
  1293.  
  1294.     if (s1 < 0 || s1 >= NUM_SOCKETS)
  1295.         return(sock_err(EBADF));
  1296.  
  1297.     if (is_used(((SocketPtr)&sockets[s1]))) 
  1298.     {
  1299.         if (s_close(s1) == -1)
  1300.             return(-1);
  1301.     }
  1302.     sock_dup_fd(s,s1);
  1303.     return(s1);
  1304. }
  1305.  
  1306.  
  1307. /*
  1308.  * s_Ioctl()
  1309.  */
  1310. s_ioctl(d, request, argp)
  1311.     int d, request;
  1312.     Ptr argp;
  1313. {
  1314.     struct    ifreq    *ifr;
  1315.     SocketPtr    sp;
  1316.     int            size;
  1317.  
  1318. #if SOCK_DEBUG >= 2
  1319.     dprintf("s_ioctl: %d, request %d\n", d,request);
  1320. #endif
  1321.  
  1322.     if (! sock_good_fd(d))
  1323.         return(sock_err(EBADF));
  1324.  
  1325.     sp = &sockets[d];
  1326.     
  1327.     /*
  1328.      * Interpret high order word to find amount of data to be copied 
  1329.      * to/from the user's address space.
  1330.      */
  1331.     size =(request &~(IOC_INOUT | IOC_VOID)) >> 16;
  1332.     
  1333.     /*
  1334.      * Zero the buffer on the stack so the user gets back something deterministic.
  1335.      */
  1336.     if ((request & IOC_OUT) && size)
  1337.         bzero((Ptr)argp, size);
  1338.  
  1339.     ifr =(struct ifreq *)argp;
  1340.     switch(request) 
  1341.     {
  1342.         /* Non-blocking I/O */
  1343.         case FIONBIO:
  1344.             sp->nonblocking = !sp->nonblocking;
  1345.             return(0);
  1346.  
  1347.          /* Number of bytes on input Q */
  1348.         case FIONREAD:
  1349.             sp->dataavail = xTCPBytesUnread(&sp->pb.tcp);
  1350.             return(sp->dataavail);
  1351.  
  1352. #ifdef IOCTL_LATER    
  1353.         /*
  1354.          *    Get interface list.  Pass in buffer and buffer length.
  1355.          *    Returns list of length one of ifreq's 
  1356.          */
  1357.         case SIOCGIFCONF: 
  1358.         {    
  1359.             struct ifconf *ifc =(struct ifconf *)argp;
  1360.             struct ifreq *req = ifc->ifc_req;
  1361.             int reqlen;
  1362.             struct sockaddr_in *addr;
  1363.             
  1364.             /*
  1365.              *    Fill in req fields for the IF's name and local IP addr.
  1366.              */
  1367.             strncpy(req->ifr_name, myIFName, IFNAMSIZ);
  1368.             addr =(struct sockaddr_in *)&req->ifr_addr;
  1369.             addr->sin_family         = AF_INET;
  1370.             addr->sin_addr.s_addr    = myIPAddress;
  1371.             addr->sin_port            = 0;
  1372.             bzero(addr->sin_zero, sizeof(addr->sin_zero));
  1373.             ifc->ifc_len = sizeof(*req);
  1374.                     
  1375.             return(0);            
  1376.         }
  1377.  
  1378.         /*
  1379.          *    Returns MTU of specified IF.
  1380.          */
  1381.         case SIOCGIFMTU: 
  1382.         {    
  1383.             /* don't check IF specification - we only have one anyway */
  1384.             *(int *)ifr->ifr_data= xMaxMTU();
  1385.             return(0);
  1386.         }
  1387.         
  1388.         /*
  1389.          *    Returns local IP Address of IF
  1390.          */
  1391.         case SIOCGIFADDR: 
  1392.         {
  1393.             struct sockaddr_in *addr;
  1394.             
  1395.             /* don't check IF specification - we only have one anyway */
  1396.  
  1397.             addr = &ifr->ifr_addr;
  1398.             addr->sin_addr.s_addr = xIPAddr();
  1399.             addr->sin_family = AF_INET;
  1400.             return(0);
  1401.         }
  1402.  
  1403.         case SIOCGIFDSTADDR:         /* For point to point, which we don't support */
  1404.             return(sock_err(EINVAL));
  1405.  
  1406.         case SIOCGIFFLAGS:             /* Returns IF flags(none yet) */
  1407.             ifr->ifr_flags = 0;
  1408.             return(0);
  1409.             
  1410.         /*
  1411.          *    Return broadcast address - net address plus all ones in host part
  1412.          */
  1413.         case SIOCGIFBRDADDR:     
  1414.         {
  1415.             struct sockaddr_in *addr;
  1416.             
  1417.             /* don't check IF specification */
  1418.             /* we only have one and its broadcast  */
  1419.                 
  1420.             addr = &ifr->ifr_addr;
  1421.             addr->sin_addr.s_addr = xIPAddr() | ~xNetMask();
  1422.             return(0);
  1423.         }
  1424. #endif IOCTL_LATER    
  1425.         default :
  1426.             return(sock_err(EOPNOTSUPP));
  1427.     }
  1428. }
  1429.  
  1430. /*
  1431.  *    s_setsockopt()
  1432.  *
  1433.  *        Set socket options. None implemented. In Unix there are...
  1434.  *
  1435.  *          SO_REUSEADDR        toggle local address reuse
  1436.  *          SO_KEEPALIVE        toggle keep connections alive
  1437.  *          SO_DONTROUTE        toggle routing bypass for  outgoing
  1438.  *                              messages
  1439.  *          SO_LINGER           linger on close if data present
  1440.  *          SO_BROADCAST        toggle   permission   to   transmit
  1441.  *                              broadcast messages
  1442.  *          SO_OOBINLINE        toggle  reception  of   out-of-band
  1443.  *                              data in band
  1444.  *          SO_SNDBUF           set buffer size for output
  1445.  *          SO_RCVBUF           set buffer size for input
  1446.  *          SO_TYPE             get the type  of  the  socket  (get
  1447.  *                              only)
  1448.  *          SO_ERROR            get and clear error on  the  socket
  1449.  *                             (get only)
  1450.  */
  1451. s_setsockopt(s, level, optname, optval, optlen)
  1452.     int s, level, optname;
  1453.     char *optval;
  1454.     int optlen;
  1455. {
  1456. #pragma unused(optval)
  1457. #pragma unused(optlen)
  1458.     SocketPtr sp;
  1459.  
  1460. #if SOCK_DEBUG >= 3
  1461.     dprintf("SETSOCKOPT:  socket: %d  option: %d  \n", s,optname);
  1462. #endif
  1463.     if (! sock_good_fd(s))
  1464.         return(sock_err(EBADF));
  1465.  
  1466.     sp = &sockets[s];
  1467.  
  1468.     /*
  1469.      * demultiplex to socket option handlers at other protocol levels.(None
  1470.      * supported yet).
  1471.      */
  1472.     switch(level) 
  1473.     {
  1474.         case SOL_SOCKET :         /* socket level option */
  1475.             switch(optname) 
  1476.             {
  1477.                 default :
  1478.                     return(0);
  1479.             }
  1480.             break;
  1481.         default :
  1482.             return(sock_err(ENOPROTOOPT));
  1483.     }
  1484.     return(0);
  1485. }
  1486.  
  1487.  
  1488. /*
  1489.  * s_spinroutine() - define a routine to be called repeatedly when
  1490.  *                   socket routines are blocked (ie. spinning)
  1491.  *
  1492.  *                     pass a NULL pointer to turn off a previously
  1493.  *                   defined spin routine.
  1494.  */
  1495. s_spinroutine(ProcPtr routine) 
  1496. {
  1497.     if (routine != NULL && !goodptr(routine))
  1498.         return(sock_err(EFAULT));
  1499.     
  1500.     spinroutine = routine;
  1501.     return(0);
  1502. }
  1503.